﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Antlr.Runtime;
using PSLib.Parsing.Common;

namespace PSLib.Parsing.Lua.ObjectModel
{
    public class Variable
    {
        public static readonly string UnknownIndexName = "$^Index";
        public static readonly string AutoAsignName = "$^AutoAsign";

        #region Constructor

        public Variable(ValueReference valueReference):this()
        {
            if (valueReference == null) throw new ArgumentNullException("valueReference");

            this.Name = Variable.AutoAsignName;
            this.SetValue(new ValueReferenceRevision(ElementPosition.GlobalStart, valueReference));
        }

        internal Variable()
        {
            this.valueReferenceRevisions = new List<ValueReferenceRevision>();
        }

        #endregion

        #region Overrides

        public override string ToString()
        {
            if (this.Name != null) return this.Name;
            return "Unknown";
        }

        #endregion

        #region Public methods

        internal void SetValue(ValueReferenceRevision valueRevision)
        {
            if (valueRevision != null) this.SetValue(valueRevision.Position, valueRevision.ValueReference);
        }

        internal void SetValue(ElementPosition position, ValueReference value)
        {
            ValueReferenceRevision revision = valueReferenceRevisions.LastOrDefault(valRef => position > valRef.Position);
            ValueReferenceRevision insertRevision = new ValueReferenceRevision(position, value);
            if (revision == null)
            {
                valueReferenceRevisions.Insert(0, insertRevision);
            }
            else
            {
                valueReferenceRevisions.Insert(valueReferenceRevisions.IndexOf(revision) + 1, insertRevision);
            }
        }

        public ValueReference GetValue(ElementPosition position, bool createNil = true)
        {
            ValueReferenceRevision revision = valueReferenceRevisions.FirstOrDefault(valRef => position > valRef.Position);
            ValueReference result = null;
            if(revision != null) result = revision.ValueReference;
            else if(createNil) result = ValueReference.Create();
            return result;
        }

        public ValueReference GetLastRevisionValue()
        {
            ValueReferenceRevision revision = valueReferenceRevisions.LastOrDefault();
            return revision != null ? revision.ValueReference : ValueReference.Create();
        }

        #endregion

        #region Properties

        public string Name { get; set; }
        public IEnumerable<ValueReferenceRevision> ValueReferenceRevisions { get { return valueReferenceRevisions; } }

        #endregion

        private List<ValueReferenceRevision> valueReferenceRevisions;
    }
}
